home *** CD-ROM | disk | FTP | other *** search
/ Aminet 44 / Aminet 44 (2001)(GTI - Schatztruhe)[!][Aug 2001].iso / Aminet / comm / mail / YAM23src.lha / Source / YAM.c < prev    next >
C/C++ Source or Header  |  2001-06-08  |  35KB  |  968 lines

  1. /***************************************************************************
  2.  
  3.  YAM - Yet Another Mailer
  4.  Copyright (C) 1995-2000 by Marcel Beck <mbeck@yam.ch>
  5.  Copyright (C) 2000-2001 by YAM Open Source Team
  6.  
  7.  This program is free software; you can redistribute it and/or modify
  8.  it under the terms of the GNU General Public License as published by
  9.  the Free Software Foundation; either version 2 of the License, or
  10.  (at your option) any later version.
  11.  
  12.  This program is distributed in the hope that it will be useful,
  13.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  GNU General Public License for more details.
  16.  
  17.  You should have received a copy of the GNU General Public License
  18.  along with this program; if not, write to the Free Software
  19.  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20.  
  21.  YAM Official Support Site :  http://www.yam.ch
  22.  YAM OpenSource project    :  http://sourceforge.net/projects/yamos/
  23.  
  24.  $Id: YAM.c,v 1.32.2.4 2001/06/08 14:05:57 laursen Exp $
  25.  
  26. ***************************************************************************/
  27.  
  28. #include "YAM.h"
  29. #include "YAM_rexx.h"
  30.  
  31. /***************************************************************************
  32.  Module: Root
  33. ***************************************************************************/
  34.  
  35. /// Global Vars
  36. //  Defines global variables and structures
  37. __near long __YAM_STACK = 32768;
  38. __near long __buffsize = 8192;
  39. __near long __MemPoolPuddleSize = 16384;
  40.  
  41. struct Library *WorkbenchBase = NULL, *IconBase = NULL;
  42. struct Library *DataTypesBase = NULL, *MUIMasterBase = NULL, *XpkBase = NULL;
  43. struct Library *OpenURLBase = NULL, *SocketBase = NULL, *CManagerBase = NULL;
  44. struct LocaleBase *LocaleBase = NULL;
  45. struct IntuitionBase *IntuitionBase = NULL;
  46.  
  47. BOOL yamFirst = TRUE, yamLast = FALSE;
  48.  
  49. struct Global *G;
  50. struct Config *C, *CE;
  51.  
  52. char *Status[9] = { "U","O","F","R","W","E","H","S","N" };
  53. char *SigNames[3] = { ".signature", ".altsignature1", ".altsignature2" };
  54. char *FolderNames[4] = { "incoming", "outgoing", "sent", "deleted" };
  55.  
  56. char *ContType[MAXCTYPE+1] =
  57. {
  58.    /*CT_TX_PLAIN */ "text/plain",
  59.    /*CT_TX_HTML  */ "text/html",
  60.    /*CT_TX_GUIDE */ "text/x-aguide",
  61.    /*CT_AP_OCTET */ "application/octet-stream",
  62.    /*CT_AP_PS    */ "application/postscript",
  63.    /*CT_AP_RTF   */ "application/rtf",
  64.    /*CT_AP_LHA   */ "application/x-lha",
  65.    /*CT_AP_LZX   */ "application/x-lzx",
  66.    /*CT_AP_ZIP   */ "application/x-zip",
  67.    /*CT_AP_AEXE  */ "application/x-amiga-executable",
  68.    /*CT_AP_SCRIPT*/ "application/x-amigados-script",
  69.    /*CT_AP_REXX  */ "application/x-rexx",
  70.    /*CT_IM_JPG   */ "image/jpeg",
  71.    /*CT_IM_GIF   */ "image/gif",
  72.    /*CT_IM_PNG   */ "image/png",
  73.    /*CT_IM_TIFF  */ "image/tiff",
  74.    /*CT_IM_ILBM  */ "image/x-ilbm",
  75.    /*CT_AU_AU    */ "audio/basic",
  76.    /*CT_AU_8SVX  */ "audio/x-8svx",
  77.    /*CT_AU_WAV   */ "audio/x-wav",
  78.    /*CT_VI_MPG   */ "video/mpeg",
  79.    /*CT_VI_MOV   */ "video/quicktime",
  80.    /*CT_VI_ANIM  */ "video/x-anim",
  81.    /*CT_VI_AVI   */ "video/x-msvideo",
  82.    /*CT_ME_EMAIL */ "message/rfc822",
  83.    NULL,
  84. };
  85. APTR ContTypeDesc[MAXCTYPE] =
  86. {
  87.    MSG_CTtextplain, MSG_CTtexthtml, MSG_CTtextaguide,
  88.    MSG_CTapplicationoctetstream, MSG_CTapplicationpostscript, MSG_CTapplicationrtf, MSG_CTapplicationlha, MSG_CTapplicationlzx, MSG_CTapplicationzip, MSG_CTapplicationamigaexe, MSG_CTapplicationadosscript, MSG_CTapplicationrexx,
  89.    MSG_CTimagejpeg, MSG_CTimagegif, MSG_CTimagepng, MSG_CTimagetiff, MSG_CTimageilbm,
  90.    MSG_CTaudiobasic, MSG_CTaudio8svx, MSG_CTaudiowav,
  91.    MSG_CTvideompeg, MSG_CTvideoquicktime, MSG_CTvideoanim, MSG_CTvideomsvideo,
  92.    MSG_CTmessagerfc822
  93. };
  94. char *wdays[7] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
  95. char *months[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
  96. char *SecCodes[5] = { "none","sign","encrypt","sign+encrypt","anonymous" };
  97. ///
  98. /// Timer Class
  99. struct TC_Data
  100. {
  101.    struct MsgPort     *port;
  102.    struct timerequest *req;
  103. } TCData = { NULL,NULL };
  104.  
  105. //  Start a one second delay
  106. void TC_Start(void)
  107. {
  108.    TCData.req->tr_node.io_Command = TR_ADDREQUEST;
  109.    TCData.req->tr_time.tv_secs    = 1;
  110.    TCData.req->tr_time.tv_micro   = 0;
  111.    SendIO((struct IORequest *)TCData.req);
  112. }
  113.  
  114. //  Frees timer resources
  115. void TC_Exit(void)
  116. {
  117.    if (TCData.port)
  118.    {
  119.       if (TCData.req)
  120.       {
  121.          if (CheckIO((struct IORequest *)TCData.req)) return;
  122.          AbortIO((struct IORequest *)TCData.req);
  123.          WaitIO((struct IORequest *)TCData.req);
  124.          CloseDevice((struct IORequest *)TCData.req);
  125.          DeleteExtIO((struct IORequest *)TCData.req);
  126.       }
  127.       DeleteMsgPort(TCData.port);
  128.    }
  129.    TCData.port = NULL;
  130.    TCData.req = NULL;
  131. }
  132.  
  133. //  Initializes timer resources
  134. BOOL TC_Init(void)
  135. {
  136.    if ((TCData.port = CreateMsgPort()))
  137.       if ((TCData.req = (struct timerequest *)CreateExtIO(TCData.port, sizeof(struct timerequest))))
  138.          if (!OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)TCData.req, 0))
  139.             return TRUE;
  140.    return FALSE;
  141. }
  142.  
  143. //  Returns TRUE if the internal editor is currently being used
  144. BOOL TC_ActiveEditor(int wrwin)
  145. {
  146.    if (G->WR[wrwin])
  147.    {
  148.       APTR ao;
  149.       get(G->WR[wrwin]->GUI.WI, MUIA_Window_ActiveObject, &ao);
  150.       return (BOOL)(ao==G->WR[wrwin]->GUI.TE_EDIT);
  151.    }
  152.    return FALSE;
  153. }
  154.  
  155. //  Dispatcher for timer class (called once every second)
  156. void TC_Dispatcher(void)
  157. {
  158.    if (CheckIO((struct IORequest *)TCData.req))
  159.    {
  160.       int i;
  161.       WaitIO((struct IORequest *)TCData.req);
  162.       if (++G->SI_Count >= C->WriteIndexes && C->WriteIndexes)
  163.          if (!TC_ActiveEditor(0) && !TC_ActiveEditor(1))
  164.          {
  165.             MA_UpdateIndexes(FALSE);
  166.             G->SI_Count = 0;
  167.          }
  168.       if (++G->GM_Count >= C->CheckMailDelay*60 && C->CheckMailDelay)
  169.       {
  170.          for (i = 0; i < MAXWR; i++) if (G->WR[i]) break;
  171.          if (i == MAXWR && !G->CO)
  172.          {
  173.             MA_PopNow(POP_TIMED,-1);
  174.             G->GM_Count = 0;
  175.          }
  176.       }
  177.       for (i = 0; i < MAXWR; i++) if (G->WR[i]) if (++G->WR[i]->AS_Count >= C->AutoSave && C->AutoSave)
  178.       {
  179.          EditorToFile(G->WR[i]->GUI.TE_EDIT, WR_AutoSaveFile(i), NULL);
  180.          G->WR[i]->AS_Count = 0;
  181.          G->WR[i]->AS_Done = TRUE;
  182.       }
  183.       TC_Start();
  184.    }
  185. }
  186. ///
  187. /// AY_PrintStatus
  188. //  Shows progress of program initialization
  189. void AY_PrintStatus(char *txt, int percent)
  190. {
  191.    set(G->AY_Text, MUIA_Gauge_InfoText, txt);
  192.    set(G->AY_Text, MUIA_Gauge_Current, percent);
  193.    DoMethod(G->App, MUIM_Application_InputBuffered);
  194. }
  195. ///
  196. /// AY_SendMailFunc
  197. //  User clicked e-mail URL in About window
  198. void SAVEDS AY_SendMailFunc(void)
  199. {
  200.    int wrwin;
  201.    if (G->MA) if ((wrwin = MA_NewNew(NULL, 0)) >= 0)
  202.    {
  203.       setstring(G->WR[wrwin]->GUI.ST_TO, "YAM Support <support@yam.ch>");
  204.       set(G->WR[wrwin]->GUI.WI, MUIA_Window_ActiveObject, G->WR[wrwin]->GUI.ST_SUBJECT);
  205.    }
  206. }
  207. MakeHook(AY_SendMailHook, AY_SendMailFunc);
  208. ///
  209. /// AY_GoPageFunc
  210. //  User clicked homepage URL in About window
  211. void SAVEDS AY_GoPageFunc(void)
  212. {
  213.    GotoURL("http://www.yam.ch/");
  214. }
  215. MakeHook(AY_GoPageHook, AY_GoPageFunc);
  216. ///
  217. /// AY_New
  218. //  Creates About window
  219. BOOL AY_New(BOOL hidden)
  220. {
  221.    char logopath[SIZE_PATHFILE];
  222.    APTR ft_text, bt_sendmail, bt_gopage;
  223.    struct DateTime dt;
  224.    char datebuf[LEN_DATSTRING];
  225.  
  226.    dt.dat_Stamp.ds_Days   = __YAM_VERDAYS;
  227.    dt.dat_Stamp.ds_Minute = 0;
  228.    dt.dat_Stamp.ds_Tick   = 0;
  229.    dt.dat_Format  = FORMAT_DOS;
  230.    dt.dat_Flags   = 0L;
  231.    dt.dat_StrDay  = NULL;
  232.    dt.dat_StrDate = datebuf;
  233.    dt.dat_StrTime = NULL;
  234.    DateToStr(&dt);
  235.  
  236.    strmfp(logopath, G->ProgDir, "Icons/logo");
  237.    G->AY_Win = WindowObject,
  238.       MUIA_Window_Title, GetStr(MSG_MA_About),
  239.       MUIA_Window_ID, MAKE_ID('C','O','P','Y'),
  240.       MUIA_Window_Activate, FALSE,
  241.       MUIA_HelpNode, "COPY",
  242.       WindowContents, VGroup,
  243.          MUIA_Background, MUII_GroupBack,
  244.          Child, HGroup,
  245.             MUIA_Group_Spacing, 0,
  246.             Child, HSpace(0),
  247.             Child, NewObject(CL_BodyChunk->mcc_Class,NULL,
  248.                MUIA_Bodychunk_File, logopath,
  249.             End,
  250.             Child, HSpace(0),
  251.          End,
  252.          Child, HCenter((VGroup,
  253.             Child, CLabel(GetStr(MSG_Copyright1)),
  254.             Child, ColGroup(2),
  255.                Child, bt_sendmail = TextObject,
  256.                   MUIA_Text_Contents, "\033c\033u\0335support@yam.ch",
  257.                   MUIA_InputMode, MUIV_InputMode_RelVerify,
  258.                End,
  259.                Child, bt_gopage = TextObject,
  260.                   MUIA_Text_Contents, "\033c\033u\0335http://www.yam.ch/",
  261.                   MUIA_InputMode, MUIV_InputMode_RelVerify,
  262.                End,
  263.             End,
  264.             Child, RectangleObject,
  265.                MUIA_Rectangle_HBar, TRUE,
  266.                MUIA_FixHeight, 8,
  267.             End,
  268.             Child, ColGroup(2),
  269.                MUIA_Group_HorizSpacing, 8,
  270.                MUIA_Group_VertSpacing, 2,
  271.                Child, Label(GetStr(MSG_Version)),
  272.                Child, LLabel(__YAM_VERSION),
  273.                Child, Label(GetStr(MSG_CompilationDate)),
  274.                Child, LLabel(datebuf),
  275.              End,
  276.          End)),
  277.          Child, G->AY_Group = PageGroup,
  278.             Child, ListviewObject,
  279.                MUIA_Listview_Input, FALSE,
  280.                MUIA_Listview_List, ft_text = FloattextObject, ReadListFrame, End,
  281.             End,
  282.             Child, ScrollgroupObject,
  283.                MUIA_Scrollgroup_FreeHoriz, FALSE,
  284.                MUIA_Scrollgroup_Contents, VGroupV,
  285.                   GroupFrame,
  286.                   Child, G->AY_List = VGroup,
  287.                      Child, TextObject,
  288.                         MUIA_Text_Contents, GetStr(MSG_UserLogin),
  289.                         MUIA_Background, MUII_TextBack,
  290.                         MUIA_Frame, MUIV_Frame_Text,
  291.                         MUIA_Text_PreParse, MUIX_C MUIX_PH,
  292.                      End,
  293.                   End,
  294.                   Child, HVSpace,
  295.                End,
  296.             End,
  297.          End,
  298.          Child, G->AY_Text = GaugeObject,
  299.             GaugeFrame,
  300.             MUIA_Gauge_InfoText, " ",
  301.             MUIA_Gauge_Horiz, TRUE,
  302.          End,
  303.          Child, G->AY_Button = TextObject,
  304.            MUIA_ShowMe, FALSE,
  305.            MUIA_Text_Contents, GetStr(MSG_ABOUT_OKAY_GAD),
  306.            MUIA_Background, MUII_ButtonBack,
  307.            MUIA_Frame, MUIV_Frame_Button,
  308.            MUIA_InputMode, MUIV_InputMode_RelVerify,
  309.            MUIA_Text_SetMax, TRUE,
  310.            MUIA_CycleChain, 1,
  311.          End,
  312.       End,
  313.    End;
  314.  
  315.    /* if the WindowObject could be created */
  316.    if (G->AY_Win)
  317.    {
  318.         /* now we create the about text */
  319.       G->AY_AboutText = AllocStrBuf(SIZE_LARGE);
  320.       G->AY_AboutText = StrBufCat(G->AY_AboutText, GetStr(MSG_Copyright2));
  321.       G->AY_AboutText = StrBufCat(G->AY_AboutText, GetStr(MSG_UsedSoftware));
  322.       G->AY_AboutText = StrBufCat(G->AY_AboutText, "\0338Magic User Interface\0332 (Stefan Stuntz)\n"
  323.                                                    "\0338TextEditor.mcc, BetterString.mcc\0332 (Allan Odgaard)\n"
  324.                                                    "\0338Toolbar.mcc\0332 (Benny Kjær Nielsen)\n"
  325.                                                    "\0338NListtree.mcc\0332 (Carsten Scholling)\n"
  326.                                                    "\0338NList.mcc, NListview.mcc\0332 (Gilles Masson)\n"
  327.                                                    "\0338XPK\0332 (Urban D. Müller, Dirk Stöcker)\n\n");
  328.       G->AY_AboutText = StrBufCat(G->AY_AboutText, GetStr(MSG_WebSite));
  329.       set(ft_text, MUIA_Floattext_Text, G->AY_AboutText);
  330.  
  331.       DoMethod(G->App, OM_ADDMEMBER, G->AY_Win);
  332.       DoMethod(bt_sendmail, MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 2, MUIM_CallHook, &AY_SendMailHook);
  333.       DoMethod(bt_gopage  , MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 2, MUIM_CallHook, &AY_GoPageHook);
  334.       DoMethod(G->AY_Win  , MUIM_Notify, MUIA_Window_CloseRequest, TRUE, G->AY_Win, 3, MUIM_Set,MUIA_Window_Open, FALSE);
  335.  
  336.       // If the close button will be pressed we close the window
  337.       DoMethod(G->AY_Button, MUIM_Notify, MUIA_Pressed, FALSE, G->AY_Win, 3, MUIM_Set, MUIA_Window_Open, FALSE, TAG_DONE);
  338.  
  339.       set(G->AY_Win, MUIA_Window_Open, !hidden);
  340.  
  341.       return TRUE;
  342.    }
  343.    return FALSE;
  344. }
  345. ///
  346. /// PopUp
  347. //  Un-iconify YAM
  348. void PopUp(void)
  349. {
  350.    int winopen;
  351.    nnset(G->App, MUIA_Application_Iconified,FALSE);
  352.    get(G->MA->GUI.WI, MUIA_Window_Open, &winopen);
  353.    if (!winopen) set(G->MA->GUI.WI, MUIA_Window_Open, TRUE);
  354.    DoMethod(G->MA->GUI.WI, MUIM_Window_ScreenToFront);
  355. }
  356. ///
  357. /// DoublestartHook
  358. //  A second copy of YAM was started
  359. void SAVEDS DoublestartFunc(void)
  360. {
  361. //   PopUp();
  362. //   ^^^^^^^^ Crap! If we want to popup the other (running) YAM,
  363. //            we can't use our own app object (NULL) pointer!
  364. }
  365. MakeHook(DoublestartHook, DoublestartFunc);
  366. ///
  367. /// StayInProg
  368. //  Makes sure that the user really wants to quit the program
  369. BOOL StayInProg(void)
  370. {
  371.    BOOL req = FALSE;
  372.    int i, fq;
  373.  
  374.    if (G->AB->Modified)
  375.    {
  376.       if (MUI_Request(G->App, G->MA->GUI.WI, 0, NULL, GetStr(MSG_MA_ABookModifiedGad), GetStr(MSG_AB_Modified)))
  377.          AB_SaveABookFunc();
  378.    }
  379.    if (G->CO || C->ConfirmOnQuit) req = TRUE;
  380.    for (i = 0; i < 4; i++) if (G->EA[i]) req = TRUE;
  381.    for (i = 0; i < 2; i++) if (G->WR[i]) req = TRUE;
  382.    get(G->App, MUIA_Application_ForceQuit, &fq);
  383.    if (fq) req = FALSE;
  384.    if (!req) return FALSE;
  385.    return (BOOL)!MUI_Request(G->App, G->MA->GUI.WI, 0, GetStr(MSG_MA_ConfirmReq), GetStr(MSG_YesNoReq), GetStr(MSG_QuitYAMReq));
  386. }
  387. ///
  388. /// Root_GlobalDispatcher
  389. //  Processes return value of MUI_Application_NewInput
  390. BOOL Root_GlobalDispatcher(ULONG app_input)
  391. {
  392.    switch (app_input)
  393.    {
  394.       case MUIV_Application_ReturnID_Quit: return (BOOL)!StayInProg();
  395.       case ID_CLOSEALL: if (!C->IconifyOnQuit) return (BOOL)!StayInProg();
  396.                         set(G->App, MUIA_Application_Iconified, TRUE); break;
  397.       case ID_RESTART:  return 2;
  398.       case ID_ICONIFY:  MA_UpdateIndexes(FALSE); break;
  399.    }
  400.    return FALSE;
  401. }
  402. ///
  403. /// Root_New
  404. //  Creates MUI application
  405. BOOL Root_New(BOOL hidden)
  406. {
  407. #define MUIA_Application_UsedClasses 0x8042e9a7
  408.    static char *classes[] = { "TextEditor.mcc", "Toolbar.mcc", "BetterString.mcc", "InfoText.mcc", "NListtree.mcc", "NList.mcc", "NListviews.mcc", NULL };
  409.    G->App = ApplicationObject,
  410.       MUIA_Application_Author     ,"Marcel Beck",
  411.       MUIA_Application_Base       ,"YAM",
  412.       MUIA_Application_Title      ,"YAM",
  413.       MUIA_Application_Version    ,"$VER: YAM " __YAM_VERSION " (" __YAM_VERDATE ")",
  414.       MUIA_Application_Copyright  ,"© 1995-2000 by Marcel Beck",
  415.       MUIA_Application_Description,GetStr(MSG_AppDescription),
  416.       MUIA_Application_UseRexx    ,FALSE,
  417.       MUIA_Application_SingleTask ,!getenv("MultipleYAM"),
  418.       MUIA_Application_UsedClasses, classes,
  419.    End;
  420.    if (G->App)
  421.    {
  422.       set(G->App, MUIA_Application_HelpFile, "YAM.guide");
  423.       set(G->App, MUIA_Application_Iconified, hidden);
  424.       DoMethod(G->App, MUIM_Notify, MUIA_Application_DoubleStart, TRUE, MUIV_Notify_Application, 2, MUIM_CallHook, &DoublestartHook);
  425.       DoMethod(G->App, MUIM_Notify, MUIA_Application_Iconified, TRUE, MUIV_Notify_Application, 2, MUIM_Application_ReturnID, ID_ICONIFY);
  426.       if (AY_New(hidden)) return TRUE;
  427.    }
  428.    return FALSE;
  429. }
  430. ///
  431.  
  432. /// Terminate
  433. //  Deallocates used memory and MUI modules and terminates
  434. void Terminate(void)
  435. {
  436.    int i;
  437. // struct Folder **flist;
  438.  
  439.    if (G->CO) { CO_FreeConfig(CE); free(CE); DisposeModule(&G->CO); }
  440.    for (i = 0; i < MAXEA; i++) DisposeModule(&G->EA[i]);
  441.    for (i = 0; i < MAXRE; i++) if (G->RE[i]) { RE_CleanupMessage(i); DisposeModule(&G->RE[i]); }
  442.    for (i = 0; i <=MAXWR; i++) if (G->WR[i]) { WR_Cleanup(i); DisposeModule(&G->WR[i]); }
  443.    if (G->TR) { TR_Cleanup(); TR_CloseTCPIP(); }
  444.    DisposeModule(&G->FO);
  445.    DisposeModule(&G->FI);
  446.    DisposeModule(&G->ER);
  447.    DisposeModule(&G->US);
  448.    if (G->MA)
  449.    {
  450.       MA_UpdateIndexes(FALSE);
  451.       G->Weights[0] = GetMUI(G->MA->GUI.LV_FOLDERS, MUIA_HorizWeight);
  452.       G->Weights[1] = GetMUI(G->MA->GUI.LV_MAILS, MUIA_HorizWeight);
  453.       SaveLayout(TRUE);
  454.       set(G->MA->GUI.WI, MUIA_Window_Open, FALSE);
  455. /*
  456.       if ((flist = FO_CreateList()))
  457.       {
  458.          for (i = 1; i <= (int)*flist; i++) ClearMailList(flist[i], TRUE);
  459.          free(flist);
  460.       }
  461. */
  462.    }
  463.    DisposeModule(&G->AB);
  464.    DisposeModule(&G->MA);
  465.    if (G->TTin) free(G->TTin);
  466.    if (G->TTout) free(G->TTout);
  467.    for (i = 0; i < MAXASL; i++) if (G->ASLReq[i]) MUI_FreeAslRequest(G->ASLReq[i]);
  468.    for (i = 0; i < MAXWR+1; i++) if (G->WR_NRequest[i].nr_stuff.nr_Msg.nr_Port) DeletePort(G->WR_NRequest[i].nr_stuff.nr_Msg.nr_Port);
  469.    if (G->AppIcon) RemoveAppIcon(G->AppIcon);
  470.    if (G->AppPort) DeletePort(G->AppPort);
  471.    if (G->RexxHost) CloseDownARexxHost(G->RexxHost);
  472.    TC_Exit();
  473.    if (G->AY_AboutText) FreeStrBuf(G->AY_AboutText);
  474.    if (G->App) MUI_DisposeObject(G->App);
  475.    for (i = 0; i < MAXICONS; i++) if (G->DiskObj[i]) FreeDiskObject(G->DiskObj[i]);
  476.    for (i = 0; i < MAXIMAGES; i++) if (G->BImage[i]) FreeBCImage(G->BImage[i]);
  477.    CO_FreeConfig(C);
  478.    ExitClasses();
  479.    if (DataTypesBase) CloseLibrary(DataTypesBase);
  480.    if (XpkBase)       CloseLibrary(XpkBase);
  481.    if (MUIMasterBase) CloseLibrary(MUIMasterBase);
  482.    CloseYAMCatalog();
  483.    if (G->Locale) CloseLocale(G->Locale);
  484.    if (LocaleBase) CloseLibrary((struct Library *)LocaleBase);
  485.    if (WorkbenchBase) CloseLibrary(WorkbenchBase);
  486.    if (IconBase) CloseLibrary(IconBase);
  487. #ifdef __ixemul__
  488.    if (RexxSysBase) CloseLibrary(RexxSysBase);
  489. #endif
  490.    if (IFFParseBase) CloseLibrary(IFFParseBase);
  491.    if (KeymapBase) CloseLibrary(KeymapBase);
  492.    if (IntuitionBase) CloseLibrary((struct Library *) IntuitionBase);
  493.    if (UtilityBase) CloseLibrary((struct Library *)UtilityBase);
  494.    free(C); free(G);
  495.    if (yamLast) exit(0);
  496. }
  497. ///
  498. /// Abort
  499. //  Shows error requester, then terminates the program
  500. void Abort(char *error)
  501. {
  502.    if (error)
  503.    {
  504.       if (MUIMasterBase) {
  505.          MUI_Request(G->App ? G->App : NULL, NULL, 0, GetStr(MSG_ErrorStartup), GetStr(MSG_Quit), error);
  506.       }
  507.       else if (IntuitionBase) {
  508.          struct EasyStruct ErrReq = {
  509.             sizeof (struct EasyStruct),
  510.             0,
  511.             NULL,
  512.             NULL,
  513.             NULL
  514.          };
  515.  
  516.          ErrReq.es_Title        = (char *)GetStr(MSG_ErrorStartup);
  517.          ErrReq.es_TextFormat   = error;
  518.          ErrReq.es_GadgetFormat = (char *)GetStr(MSG_Quit);
  519.  
  520.          EasyRequest(NULL, &ErrReq, NULL, error);
  521.       }
  522.       else puts(error);
  523.    }
  524.    yamLast = TRUE;
  525.    Terminate();
  526. }
  527. ///
  528. /// CheckMCC
  529. //  Checks if a certain version of a MCC is available
  530. BOOL CheckMCC(char *name, int minver, int minrev, BOOL req)
  531. {
  532.    Object *obj;
  533.    BOOL success = FALSE;
  534.  
  535.    obj = MUI_NewObject(name, TAG_DONE);
  536.    if (obj) {
  537.       ULONG tmp;
  538.       int ver, rev;
  539.  
  540.       get(obj, MUIA_Version, &tmp);
  541.       ver = (int)tmp;
  542.       get(obj, MUIA_Revision, &tmp);
  543.       rev = (int)tmp;
  544.  
  545.       if (ver > minver || (ver == minver && rev >= minrev)) {
  546.          success = TRUE;
  547.       }
  548.       MUI_DisposeObject(obj);
  549.    }
  550.  
  551.    if (!success && req) {
  552.       static char errorlib[SIZE_DEFAULT];
  553.       sprintf(errorlib, GetStr(MSG_ErrorLib), name, minver);
  554.       Abort(errorlib);
  555.    }
  556.  
  557.    return success;
  558. }
  559. ///
  560. /// InitLib
  561. //  Opens a library
  562. struct Library *InitLib(char *libname, int version, int revision, BOOL required, BOOL close)
  563. {
  564.    struct Library *lib = OpenLibrary(libname, version);
  565.    if (lib && revision) if (lib->lib_Version == version && lib->lib_Revision < revision) { CloseLibrary(lib); lib = NULL; }
  566.    if (!lib && required)
  567.    {
  568.       static char errorlib[SIZE_DEFAULT];
  569.       sprintf(errorlib, GetStr(MSG_ErrorLib), libname, version);
  570.       Abort(errorlib);
  571.    }
  572.    if (lib && close) CloseLibrary(lib);
  573.    return lib;
  574. }
  575. ///
  576. /// SetupAppIcons
  577. //  Sets location of mailbox status icon on workbench screen
  578. void SetupAppIcons(void)
  579. {
  580.    int i;
  581.    for (i = 0; i < 4; i++) if (G->DiskObj[i])
  582.    {
  583.       G->DiskObj[i]->do_CurrentX = C->IconPositionX;
  584.       G->DiskObj[i]->do_CurrentY = C->IconPositionY;
  585.    }
  586. }
  587. ///
  588. /// Initialise2
  589. //  Phase 2 of program initialization (after user logs in)
  590. void Initialise2(BOOL hidden)
  591. {
  592.    BOOL newfolders = FALSE;
  593.    int i;
  594.    struct Folder *folder, **oldfolders = NULL;
  595.  
  596.    AY_PrintStatus(GetStr(MSG_LoadingConfig), 30);
  597.    CO_SetDefaults(C, -1);
  598.    CO_LoadConfig(C, G->CO_PrefsFile, &oldfolders);
  599.    CO_Validate(C, FALSE);
  600.    AY_PrintStatus(GetStr(MSG_CreatingGUI), 40);
  601.    if (!(G->MA = MA_New()) || !(G->AB = AB_New())) Abort(GetStr(MSG_ErrorMuiApp));
  602.    MA_SetupDynamicMenus();
  603.    MA_ChangeSelectedFunc();
  604.    SetupAppIcons();
  605.    LoadLayout();
  606.    set(G->MA->GUI.LV_FOLDERS, MUIA_HorizWeight, G->Weights[0]);
  607.    set(G->MA->GUI.LV_MAILS,   MUIA_HorizWeight, G->Weights[1]);
  608.    AY_PrintStatus(GetStr(MSG_LoadingFolders), 50);
  609.    if (!FO_LoadTree(CreateFilename(".folders")) && oldfolders)
  610.    {
  611.       for (i = 0; i < 100; i++) if (oldfolders[i]) DoMethod(G->MA->GUI.NL_FOLDERS, MUIM_NList_InsertSingle, oldfolders[i], MUIV_NList_Insert_Bottom);
  612.       newfolders = TRUE;
  613.    }
  614.    if (oldfolders) { for (i = 0; oldfolders[i]; i++) free(oldfolders[i]); free(oldfolders); }
  615.    if (!FO_GetFolderByType(FT_INCOMING,NULL)) newfolders |= FO_CreateFolder(FT_INCOMING, FolderNames[0], GetStr(MSG_MA_Incoming));
  616.    if (!FO_GetFolderByType(FT_OUTGOING,NULL)) newfolders |= FO_CreateFolder(FT_OUTGOING, FolderNames[1], GetStr(MSG_MA_Outgoing));
  617.    if (!FO_GetFolderByType(FT_SENT    ,NULL)) newfolders |= FO_CreateFolder(FT_SENT    , FolderNames[2], GetStr(MSG_MA_Sent));
  618.    if (!FO_GetFolderByType(FT_DELETED ,NULL)) newfolders |= FO_CreateFolder(FT_DELETED , FolderNames[3], GetStr(MSG_MA_Deleted));
  619.    if (newfolders) FO_SaveTree(CreateFilename(".folders"));
  620.    AY_PrintStatus(GetStr(MSG_RebuildIndices), 60);
  621.    MA_UpdateIndexes(TRUE);
  622.    AY_PrintStatus(GetStr(MSG_LoadingFolders), 75);
  623.    for (i = 0; ; i++)
  624.    {
  625.       DoMethod(G->MA->GUI.NL_FOLDERS, MUIM_NList_GetEntry, i, &folder);
  626.       if (!folder) break;
  627.       if ((folder->Type == FT_INCOMING || folder->Type == FT_OUTGOING || folder->Type == FT_DELETED || C->LoadAllFolders) && !(folder->XPKType&1)) MA_GetIndex(folder);
  628.       else if (folder->Type != FT_SEPARATOR) folder->LoadedMode = MA_LoadIndex(folder, FALSE);
  629.       DoMethod(G->App, MUIM_Application_InputBuffered);
  630.    }
  631.    G->NewMsgs = -1;
  632.    MA_ChangeFolder(FO_GetFolderByType(FT_INCOMING,NULL));
  633.    AY_PrintStatus(GetStr(MSG_LoadingABook), 90);
  634.    AB_LoadTree(G->AB_Filename, FALSE, FALSE);
  635.    if (!(G->RexxHost = SetupARexxHost("YAM", NULL))) Abort(GetStr(MSG_ErrorARexx));
  636.    AY_PrintStatus("", 100);
  637.    set(G->MA->GUI.WI, MUIA_Window_Open, !hidden);
  638.    set(G->AY_Win, MUIA_Window_Open, FALSE);
  639.    set(G->AY_Text, MUIA_ShowMe, FALSE);
  640.      set(G->AY_Button, MUIA_ShowMe, TRUE);
  641. }
  642. ///
  643. /// Initialise
  644. //  Phase 1 of program initialization (before user logs in)
  645. void Initialise(BOOL hidden)
  646. {
  647.    static char iconfile[SIZE_PATHFILE];
  648.    char iconpath[SIZE_PATH];
  649.    char *icnames[MAXICONS] = { "empty", "old", "new", "check" };
  650.    char *imnames[MAXIMAGES] = { "status_unread", "status_old", "status_forward",
  651.       "status_reply", "status_waitsend", "status_error", "status_hold",
  652.       "status_sent", "status_new", "status_delete", "status_download",
  653.       "status_group", "status_urgent", "status_attach", "status_report",
  654.       "status_crypt", "status_signed" };
  655.    int i;
  656.  
  657.    DateStamp(&G->StartDate);
  658.  
  659.    /* First open locale.library, so we can display a translated error requester
  660.       in case some of the other libraries can't be opened. */
  661.    if ((LocaleBase = (struct LocaleBase *)InitLib("locale.library", 38, 0, TRUE, FALSE))) G->Locale = OpenLocale(NULL);
  662.    OpenYAMCatalog();
  663.  
  664.    UtilityBase = (struct UtilityBase *)InitLib("utility.library", 36, 0, TRUE, FALSE);
  665.    KeymapBase = InitLib("keymap.library", 36, 0, TRUE, FALSE);
  666.    IFFParseBase = InitLib("iffparse.library", 36, 0, TRUE, FALSE);
  667. #ifdef __ixemul__
  668.    RexxSysBase = InitLib("rexxsyslib.library", 36, 0, TRUE, FALSE);
  669. #endif
  670.    MUIMasterBase = InitLib("muimaster.library", 19, 0, TRUE, FALSE);
  671.  
  672.    /* We can't use CheckMCC() due to a bug in Toolbar.mcc! */
  673.    InitLib("mui/Toolbar.mcc", 15, 6, TRUE, TRUE);
  674.  
  675.    CheckMCC(MUIC_NList, 19, 98, TRUE);
  676.    CheckMCC(MUIC_NListtree, 18, 7, TRUE);
  677.  
  678.    if (!InitClasses()) Abort(GetStr(MSG_ErrorClasses));
  679.    if (!Root_New(hidden)) Abort(FindPort("YAM") ? NULL : GetStr(MSG_ErrorMuiApp));
  680.    AY_PrintStatus(GetStr(MSG_InitLibs), 10);
  681.    XpkBase = InitLib(XPKNAME, 0, 0, FALSE, FALSE);
  682.    if ((DataTypesBase = InitLib("datatypes.library", 39, 0, FALSE, FALSE)))
  683.       if (CheckMCC("Dtpic.mui", 0, 0, FALSE)) G->DtpicSupported = TRUE;
  684.    if (!TC_Init()) Abort(GetStr(MSG_ErrorTimer));
  685.    for (i = 0; i < MAXASL; i++)
  686.       if (!(G->ASLReq[i] = MUI_AllocAslRequestTags(ASL_FileRequest, ASLFR_RejectIcons, TRUE,
  687.          TAG_END))) Abort(GetStr(MSG_ErrorAslStruct));
  688.    G->AppPort = CreatePort(NULL, 0);
  689.    for (i = 0; i < 3; i++)
  690.    {
  691.       G->WR_NRequest[i].nr_stuff.nr_Msg.nr_Port = CreatePort(NULL, 0);
  692.       G->WR_NRequest[i].nr_Name = (UBYTE *)G->WR_Filename[i];
  693.       G->WR_NRequest[i].nr_Flags = NRF_SEND_MESSAGE;
  694.    }
  695.    srand(GetDateStamp());
  696.    AY_PrintStatus(GetStr(MSG_LoadingGFX), 20);
  697.    strmfp(iconpath, G->ProgDir, "Icons");
  698.    for (i = 0; i < MAXICONS; i++)
  699.    {
  700.       strmfp(iconfile, iconpath, icnames[i]);
  701.       G->DiskObj[i] = GetDiskObject(iconfile);
  702.    }
  703.    for (i = 0; i < MAXIMAGES; i++)
  704.    {
  705.       strmfp(iconfile, iconpath, imnames[i]);
  706.       G->BImage[i] = LoadBCImage(iconfile);
  707.       DoMethod(G->App, MUIM_Application_InputBuffered);
  708.    }
  709. }
  710. ///
  711. /// SendWaitingMail
  712. //  Sends pending mail on startup
  713. void SendWaitingMail(void)
  714. {
  715.    struct Mail *mail;
  716.    BOOL doit = TRUE;
  717.    int tots = 0, hidden;
  718.    struct Folder *fo = FO_GetFolderByType(FT_OUTGOING, NULL);
  719.  
  720.    get(G->App, MUIA_Application_Iconified, &hidden);
  721.    for (mail = fo->Messages; mail; mail = mail->Next) if (mail->Status != STATUS_HLD) tots++;
  722.    if (!tots) return;
  723.    MA_ChangeFolder(fo);
  724.    if (!hidden) doit = MUI_Request(G->App, G->MA->GUI.WI, 0, NULL, GetStr(MSG_YesNoReq), GetStr(MSG_SendStartReq));
  725.    if (doit) MA_Send(SEND_ALL);
  726. }
  727. ///
  728. /// DoStartup
  729. //  Performs different checks/cleanup operations on startup
  730. void DoStartup(BOOL nocheck, BOOL hide)
  731. {
  732.  
  733.    if (C->CleanupOnStartup) DoMethod(G->App, MUIM_CallHook, &MA_DeleteOldHook);
  734.    if (C->RemoveOnStartup) DoMethod(G->App, MUIM_CallHook, &MA_DeleteDeletedHook);
  735.    if (C->CheckBirthdates && !nocheck && !hide) AB_CheckBirthdates();
  736.    if (TR_IsOnline())
  737.    {
  738.       if (C->GetOnStartup && !nocheck) {
  739.          MA_PopNow(POP_START,-1);
  740.          if (G->TR) DisposeModule(&G->TR);
  741.       }
  742.       if (C->SendOnStartup && !nocheck) {
  743.          SendWaitingMail();
  744.          if (G->TR) DisposeModule(&G->TR);
  745.       }
  746.    }
  747. }
  748. ///
  749. /// Login
  750. //  Allows automatical login for AmiTCP-Genesis users
  751. #ifdef __STORM__
  752. struct Library *GenesisBase;
  753. #endif
  754. void Login(char *user, char *password, char *maildir, char *prefsfile)
  755. {
  756. #ifndef __STORM__
  757.    struct Library *GenesisBase;
  758. #endif
  759.    struct genUser *guser;
  760.    BOOL terminate = FALSE, loggedin = FALSE;
  761.  
  762.    if ((GenesisBase = OpenLibrary("genesis.library", 1)))
  763.    {
  764.       if ((guser = GetGlobalUser()))
  765.       {
  766.          terminate = !(loggedin = US_Login(guser->us_name, "\01", maildir, prefsfile));
  767.          FreeUser(guser);
  768.       }
  769.       CloseLibrary(GenesisBase);
  770.    }
  771.    if (!loggedin && !terminate) terminate = !US_Login(user, password, maildir, prefsfile);
  772.    if (terminate) Abort(NULL);
  773. }
  774. ///
  775. /// GetDST
  776. //  Checks if daylight saving time is active
  777. int GetDST(void)
  778. {
  779.    int i;
  780.    char *dst;
  781.  
  782.    if((dst = getenv("IXGMTOFFSET")))
  783.    {
  784.       return dst[4]?2:1;
  785.    }
  786.  
  787.    dst = getenv("SUMMERTIME");
  788.    if (!dst) return 0;
  789.    for (i = 0; i < 11; i++)
  790.    {
  791.       while (*dst != ':') if (!*dst++) return 0;
  792.       dst++;
  793.    }
  794.    return (*dst == 'Y' ? 2 : 1);
  795. }
  796. ///
  797.  
  798. /// Main
  799. //  Program entry point, main loop
  800. #ifdef __GNUC__
  801. void STACKEXT main(int argc, char **argv)
  802. #else
  803. void main(int argc, char **argv)
  804. #endif
  805. {
  806.    struct NewRDArgs nrda;
  807.    struct { STRPTR user;
  808.             STRPTR password;
  809.             STRPTR maildir;
  810.             STRPTR prefsfile;
  811.             LONG   nocheck;
  812.             LONG   hide;
  813.             LONG   debug;
  814.             STRPTR mailto;
  815.             STRPTR subject;
  816.             STRPTR letter;
  817.             STRPTR *attach;
  818.           } args = { NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, NULL, NULL, NULL, NULL };
  819.    int wrwin, err, ret;
  820.    char **sptr, progdir[SIZE_PATH];
  821.    ULONG signals, appsigs, timsigs, notsigs0, notsigs1, notsigs2, rexsigs;
  822.    struct Message *msg;
  823.    struct User *user;
  824.    BPTR progdirlock, yamlock, oldcdirlock;
  825.  
  826.    IntuitionBase = (struct IntuitionBase *) InitLib("intuition.library", 36, 0, TRUE, FALSE);
  827.    IconBase = InitLib("icon.library", 36, 0, TRUE, FALSE);
  828.    WorkbenchBase = InitLib("workbench.library", 36, 0, TRUE, FALSE);
  829.  
  830. #ifdef __ixemul__
  831.    if(0 == argc) _WBenchMsg=(struct WBStartup *)argv;
  832. #endif
  833.  
  834.    nrda.Template = "USER/K,PASSWORD/K,MAILDIR/K,PREFSFILE/K,NOCHECK/S,HIDE/S,DEBUG/S,MAILTO/K,SUBJECT/K,LETTER/K,ATTACH/M";
  835.    nrda.ExtHelp = NULL;
  836.    nrda.Window = NULL;
  837.    nrda.Parameters = (LONG *)&args;
  838.    nrda.FileParameter = -1;
  839.    nrda.PrgToolTypesOnly = FALSE;
  840.    if ((err = NewReadArgs(_WBenchMsg, &nrda)))
  841.    {
  842.       PrintFault(err, "YAM");
  843.       NewFreeArgs(&nrda);
  844.       if (WorkbenchBase) CloseLibrary(WorkbenchBase);
  845.       if (IconBase) CloseLibrary(IconBase);
  846.       if (IntuitionBase) CloseLibrary((struct Library *) IntuitionBase);
  847.       exit(5);
  848.    }
  849.    if ((progdirlock = GetProgramDir()))
  850.       NameFromLock(progdirlock, progdir, SIZE_PATH);
  851.    else
  852.    {
  853.       strcpy(progdir, "YAM:");
  854.       SetProgramDir(Lock(progdir, ACCESS_READ));
  855.    }
  856.    yamlock = Lock(progdir, ACCESS_READ);
  857.    oldcdirlock = CurrentDir(yamlock);
  858.    while (1)
  859.    {
  860.       G = calloc(1,sizeof(struct Global));
  861.       C = calloc(1,sizeof(struct Config));
  862.       strcpy(G->ProgDir, progdir);
  863.       if (!args.maildir) strcpy(G->MA_MailDir, progdir);
  864.       args.hide = -args.hide; args.nocheck = -args.nocheck;
  865.       G->TR_Debug = -args.debug;
  866.       G->TR_Allow = TRUE;
  867.       G->CO_DST = GetDST();
  868.       if (yamFirst)
  869.       {
  870.          Initialise(args.hide);
  871.          Login(args.user, args.password, args.maildir, args.prefsfile);
  872.          Initialise2(args.hide);
  873.          DoMethod(G->App, MUIM_Application_Load, MUIV_Application_Load_ENVARC);
  874.          AppendLog(0, GetStr(MSG_LOG_Started), "", "", "", "");
  875.          MA_StartMacro(MACRO_STARTUP, NULL);
  876.          DoStartup(args.nocheck, args.hide);
  877.          if (args.mailto || args.letter || args.subject || args.attach) if ((wrwin = MA_NewNew(NULL, 0)) >= 0)
  878.          {
  879.             if (args.mailto) setstring(G->WR[wrwin]->GUI.ST_TO, args.mailto);
  880.             if (args.subject) setstring(G->WR[wrwin]->GUI.ST_SUBJECT, args.subject);
  881.             if (args.letter) FileToEditor(args.letter, G->WR[wrwin]->GUI.TE_EDIT);
  882.             if (args.attach) for (sptr = (char**)args.attach; *sptr; sptr++)
  883.                if (FileSize(*sptr) >= 0) WR_AddFileToList(wrwin, *sptr, NULL, FALSE);
  884.          }
  885.          yamFirst = FALSE;
  886.       }
  887.       else
  888.       {
  889.          Initialise(FALSE);
  890.          Login(NULL, NULL, NULL, NULL);
  891.          Initialise2(FALSE);
  892.          DoMethod(G->App, MUIM_Application_Load, MUIV_Application_Load_ENVARC);
  893.       }
  894.       user = US_GetCurrentUser();
  895.       AppendLogNormal(1, GetStr(MSG_LOG_LoggedIn), user->Name, "", "", "");
  896.       AppendLogVerbose(1, GetStr(MSG_LOG_LoggedInVerbose), user->Name, G->CO_PrefsFile, G->MA_MailDir, "");
  897.       TC_Start();
  898.       appsigs  = 1<<G->AppPort->mp_SigBit;
  899.       timsigs  = 1<<TCData.port->mp_SigBit;
  900.       notsigs0 = 1<<G->WR_NRequest[0].nr_stuff.nr_Msg.nr_Port->mp_SigBit;
  901.       notsigs1 = 1<<G->WR_NRequest[1].nr_stuff.nr_Msg.nr_Port->mp_SigBit;
  902.       notsigs2 = 1<<G->WR_NRequest[2].nr_stuff.nr_Msg.nr_Port->mp_SigBit;
  903.       rexsigs  = 1<<G->RexxHost->port->mp_SigBit;
  904.       while (!(ret = Root_GlobalDispatcher(DoMethod(G->App, MUIM_Application_NewInput, &signals))))
  905.       {
  906.          if (signals)
  907.          {
  908.             signals = Wait(signals | timsigs | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F | appsigs | notsigs0 | notsigs1 | rexsigs);
  909.             if (signals & SIGBREAKF_CTRL_C) break;
  910.             if (signals & SIGBREAKF_CTRL_F) PopUp();
  911.             if (signals & timsigs) TC_Dispatcher();
  912.             if (signals & rexsigs) ARexxDispatch(G->RexxHost);
  913.             if (signals & appsigs)
  914.             {
  915.                struct AppMessage *apmsg;
  916.                while ((apmsg = (struct AppMessage *)GetMsg(G->AppPort)))
  917.                {
  918.                   if (apmsg->am_Type == AMTYPE_APPICON)
  919.                   {
  920.                      PopUp();
  921.                      if (apmsg->am_NumArgs)
  922.                      {
  923.                         int wrwin;
  924.                         if      (G->WR[0]) wrwin = 0;
  925.                         else if (G->WR[1]) wrwin = 1;
  926.                         else wrwin = MA_NewNew(NULL, 0);
  927.                         if (wrwin >= 0) WR_App(wrwin, apmsg);
  928.                      }
  929.                   }
  930.                   ReplyMsg((struct Message *)apmsg);
  931.                }
  932.             }
  933.             if (signals & notsigs0)
  934.             {
  935.                while ((msg = GetMsg(G->WR_NRequest[0].nr_stuff.nr_Msg.nr_Port))) ReplyMsg(msg);
  936.                if (G->WR[0]) FileToEditor(G->WR_Filename[0], G->WR[0]->GUI.TE_EDIT);
  937.             }
  938.             if (signals & notsigs1)
  939.             {
  940.                while ((msg = GetMsg(G->WR_NRequest[1].nr_stuff.nr_Msg.nr_Port))) ReplyMsg(msg);
  941.                if (G->WR[1]) FileToEditor(G->WR_Filename[1], G->WR[1]->GUI.TE_EDIT);
  942.             }
  943.             if (signals & notsigs2)
  944.             {
  945.                while ((msg = GetMsg(G->WR_NRequest[2].nr_stuff.nr_Msg.nr_Port))) ReplyMsg(msg);
  946.                if (G->WR[2]) FileToEditor(G->WR_Filename[2], G->WR[2]->GUI.TE_EDIT);
  947.             }
  948.          }
  949.       }
  950.       if (C->SendOnQuit && !args.nocheck) if (TR_IsOnline()) SendWaitingMail();
  951.       if (C->CleanupOnQuit) DoMethod(G->App, MUIM_CallHook, &MA_DeleteOldHook);
  952.       if (C->RemoveOnQuit) DoMethod(G->App, MUIM_CallHook, &MA_DeleteDeletedHook);
  953.       if (ret == 1)
  954.       {
  955.          yamLast = TRUE;
  956.          AppendLog(99, GetStr(MSG_LOG_Terminated), "", "", "", "");
  957.          MA_StartMacro(MACRO_QUIT, NULL);
  958.          CurrentDir(oldcdirlock);
  959.          UnLock(yamlock);
  960.          NewFreeArgs(&nrda);
  961.       }
  962.       FreeData2D(&Header);
  963.       Terminate();
  964.    }
  965. }
  966. ///
  967.  
  968.